#pragma once

#include<iostream>
#include<queue>
#include<pthread.h>
using namespace std;
static int defaultcap=1;

template<class T>
class BlockQueue
{  
public:
    BlockQueue(int maxcap=defaultcap):max_cap(maxcap)
    {
        pthread_mutex_init(&mutex_,nullptr);
        pthread_cond_init(&p_cond_,nullptr);
        pthread_cond_init(&c_cond_,nullptr);
    }
    void Push(const T& in)
    {
        //生产者
        pthread_mutex_lock(&mutex_);
        if(q_.size()==max_cap)
        {
            pthread_cond_wait(&p_cond_,&mutex_);  //当队列中没有数据时，激活条件变量同时把锁释放
        }
        q_.push(in);
        //因为我们创建的是一个简单的生产消费模型，且最大容量为1，所以当我们生产一个数据后就达到了最大容量，需要激活消费者
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&mutex_);
    }
    T Pop()
    {
        //消费者
        pthread_mutex_lock(&mutex_);
        if(q_.size()==0)
        {
            pthread_cond_wait(&c_cond_,&mutex_);
        }
        T out=q_.front();
        q_.pop();
        pthread_cond_signal(&p_cond_);
        pthread_mutex_unlock(&mutex_);
        return out;
    }
    ~BlockQueue()
    {
        pthread_cond_destroy(&p_cond_);
        pthread_cond_destroy(&c_cond_);
        pthread_mutex_destroy(&mutex_);
    }
private:
    queue<T> q_;  //共享资源
    int max_cap;  //最大容量
    pthread_mutex_t mutex_;   //只需要有一把锁就够了，在我们创建的这个简单的生产消费模型中不存在同时生产和消费的场景
    pthread_cond_t p_cond_;
    pthread_cond_t c_cond_;   //创建了两个条件变量，因为生产者和消费者启动的条件不一样
};